package com.thread.threadfirst.studyThread1;

import java.math.BigDecimal;
import java.util.concurrent.TimeUnit;

/**
 * 7、对业务方法加锁
 * 对业务方法不加锁
 * 容易产生脏读（dirtyRead）
 */
public class Account {
    public String name;
    public BigDecimal balance;

    public synchronized void set(String name, BigDecimal balance) {
        this.name = name;

        try {
            Thread.sleep(2000);
        } catch (Exception e) {
            e.printStackTrace();
        }

        this.balance = balance;
    }

    /**
     * 如果想要读到的是已变化后的值，就在getBalance()方法上加锁
     *
     * @param name
     * @return
     */
    public synchronized BigDecimal getBalance(String name) {
        return balance;
    }

    /**
     * 注意：此处的读balance是主线程（即main线程）来读的，而不是子线程读的，在main()中的sleep也是对主线程sleep而不是子线程sleep，
     * 而此处如果主线程没有sleep，子线程也没有sleep2秒（2000毫秒），主线程还是读不到变化后的值的，需要主线程sleep一些时间后才能读到变化后的值（即变化并不会立即读到）
     *
     * @param args
     */
    public static void main(String[] args) {
        Account a = new Account();
        new Thread(() -> a.set("lufei", new BigDecimal("100.0"))).start();

        //注意如果上面的读和写都已加锁，还是打印出2个null，那么是主线程获取了CPU执行权，而以下sleep1秒，保证让主线程后执行。
//        try {
//            TimeUnit.SECONDS.sleep(1);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }

        System.out.println(a.getBalance("lufei"));

//        try {
//            TimeUnit.SECONDS.sleep(2);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
        System.out.println(a.getBalance("lufei"));
//        System.out.println(a.name);
//        System.out.println(a.balance);

    }
}
